package main

import (
	"fmt"
	"unsafe"
)

func main() {
	var arr = [6]int{1, 2, 3, 4, 5, 6}
	fmt.Println("数组长度: ", len(arr))
	fmt.Println("数组大小: ", unsafe.Sizeof(arr))

	var arr1 [6]int // [0, 0, 0, 0, 0, 0]
	fmt.Printf("%T\n", arr1)

	var arr2 = [...]int{
		99: 39, // 将第100个元素(下标值为99)的值赋值为39, 其余元素为0
	}
	fmt.Printf("%T\n", arr2) // [100]int

	// 切片
	var nums = []int{1, 2, 3, 4, 5, 6}
	fmt.Println(len(nums)) // 6
	// 通过 Go 内置函数 append， 可以动态向切片中添加元素
	nums = append(nums, 7) // 切片变为 [1, 2, 3, 4, 5, 6, 7]
	fmt.Println(len(nums)) // 7

	// type slice struct {
	// 	array unsafe.Pointer // 指向底层数组的指针
	// 	len int // 切片的长度, 即切片中当前元素的个数
	// 	cap int // 底层数组的长度, 也是切片的最大容量, cap >= len
	// }
	// 通过 make 来创建切片, 并指定底层数组的长度
	sl := make([]byte, 6, 10) // 其中 cap = 10, len = 6
	fmt.Printf("%T\n", sl)    // []uint8
	sl = make([]byte, 6)      // cap = len = 6
	fmt.Printf("%T\n", sl)    // []uint8

	// 采用 array[low:high:max]语法基于一个已经存在的数组创建切片, 也称为数组的切片化
	// low = 3, high = 5, max = 6
	// len = high - low = 2, cap = max - low = 3
	si := arr[3:5:6]
	fmt.Printf("%T\n", si) // []int

	// 基于数组创建的切片相当于打开了一个访问与修改数组的窗口
	// 切片之于数组就像是文件描述符之于文件
	// 避免参数传递时的较大性能开销

	// 基于切片创建切片
	si = append(si, 1, 2)

	// 切片的动态扩容, 当追加数据时, 如果 len == cap, 也就是说切片底层数组没有空闲空间来存储追加的值了, Go运行时就会对这个切片扩容(cap 翻倍)
	fmt.Println(len(si), cap(si)) // 4 6
	si = append(si, 7, 10)
	fmt.Println(len(si), cap(si)) // 6 6
	si = append(si, 0)
	fmt.Println(len(si), cap(si)) // 7 12

	u := [...]int{11, 12, 13, 14, 15}
	fmt.Println("array: ", u) // [11, 12, 13, 14, 15]
	s := u[1:3]
	fmt.Printf("slice(len=%d, cap=%d): %v\n", len(s), cap(s), s) // [12, 13]
	s = append(s, 24)
	fmt.Println("after append 24, array:", u)                                     // [11 12 13 24 15]
	fmt.Printf("after append 24, slice(len=%d, cap=%d): %v\n", len(s), cap(s), s) // [12 13 24]
	s = append(s, 25)
	fmt.Println("after append 25, array:", u)                                     // [11 12 13 24 25]
	fmt.Printf("after append 25, slice(len=%d, cap=%d): %v\n", len(s), cap(s), s) // [12 13 24 25]
	s = append(s, 26)                                                             // 这里扩充到两倍, s绑定的数组改变了
	fmt.Println("after append 26, array:", u)                                     // [11 12 13 24 25]
	fmt.Printf("after append 26, slice(len=%d, cap=%d): %v\n", len(s), cap(s), s) // [12 13 24 25 26]
	s[0] = 22
	fmt.Println("after reassign 1st elem of slice, array:", u)                                     // [11 12 13 24 25]
	fmt.Printf("after reassign 1st elem of slice, slice(len=%d, cap=%d): %v\n", len(s), cap(s), s) // 22 13 24 25 26

}
